//******************************************************************************
//    CG^2 - Client of GUCAS Gateway
//    Copyright (C) 2010 Rui Diao
//
//    This program is free software: you can redistribute it and/or modify
//    it under the terms of the GNU General Public License as published by
//    the Free Software Foundation, either version 3 of the License, or
//    (at your option) any later version.
//    This program is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//    GNU General Public License for more details.
//    You should have received a copy of the GNU General Public License
//    along with this program.  If not, see <http://www.gnu.org/licenses/>.
//
//    Author's Email: diaorui@lsec.cc.ac.cn doraemonok@163.com
//    Website: http://lsec.cc.ac.cn/~diaorui/software/cg2/
//******************************************************************************

#include "mainWindow.h"

MainWindow::MainWindow() {
    setupUi(this);
    QIcon icon(":/cg2.png");
    icon.addPixmap(QPixmap(QString::fromUtf8(":/cg2.png")), QIcon::Normal, QIcon::Off);
    trayIcon = new QSystemTrayIcon(this);
    trayIcon->setIcon(icon);
    trayIcon->show();
    QMenu *trayMenu = new QMenu(this);
    QAction *quitAction = new QAction(tr("退出"), this);
    QAction *showAction = new QAction(tr("显示主窗口"), this);
    QAction *hideAction = new QAction(tr("隐藏主窗口"), this);
    trayMenu->addAction(showAction);
    trayMenu->addAction(hideAction);
    trayMenu->addAction(quitAction);
    trayIcon->setContextMenu(trayMenu);
    //trayIcon->showMessage(tr("网关客户端"), tr("最小化到这里"), QSystemTrayIcon::Information, 5000);
    
    httpLogin = new QHttp(this);
    httpConnect = new QHttp(this);
    httpMessage = new QHttp(this);
    httpRemainFee = new QHttp(this);
    httpDisconnect = new QHttp(this);
    timerUpdate = new QTimer(this);
    httpKickOff = new QHttp(this);
    host = "auth.gucas.ac.cn";
    userAgent = "Mozilla/5.0 (X11; U; Linux i686; zh-CN; rv:1.9.0.17) Gecko/2010010604 Ubuntu/9.04 (jaunty) Firefox/3.0.17";
    labelNameList << "labelLocalUp" << "labelLocalDown" << "labelDomesticUp" << "labelDomesticDown" << "labelInternationalUp" << "labelInternationalDown";
    quit = false;
    
    readSettings();
    
    connect(pushButtonConnect, SIGNAL(clicked()), this, SLOT(onPushBottonConnectClicked()));
    connect(httpLogin, SIGNAL(responseHeaderReceived(const QHttpResponseHeader &)), this, SLOT(getCookie(const QHttpResponseHeader &)));
    connect(httpLogin, SIGNAL(done(bool)), this, SLOT(checkLogin(bool)));
    connect(httpConnect, SIGNAL(done(bool)), this, SLOT(checkConnect(bool)));
    connect(httpMessage, SIGNAL(done(bool)), this, SLOT(checkMessage(bool)));
    connect(httpRemainFee, SIGNAL(done(bool)), this, SLOT(checkRemainFee(bool)));
    connect(timerUpdate, SIGNAL(timeout()), this, SLOT(updateMessage()));
    connect(timerUpdate, SIGNAL(timeout()), this, SLOT(updateRemainFee()));
    connect(httpDisconnect, SIGNAL(done(bool)), this, SLOT(onDisconnected(bool)));
    connect(trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(onSystemTrayIconClicked(QSystemTrayIcon::ActivationReason)));
    connect(quitAction, SIGNAL(triggered()), this, SLOT(close()));
    connect(showAction, SIGNAL(triggered()), this, SLOT(show()));
    connect(hideAction, SIGNAL(triggered()), this, SLOT(hide()));
    connect(checkBoxAlwaysOnTop, SIGNAL(stateChanged(int)), this, SLOT(alwaysOnTopChanged(int)));
    connect(httpKickOff, SIGNAL(done(bool)), this, SLOT(connectNetwork()));
    //setWindowFlags(Qt::X11BypassWindowManagerHint);
    setGeometry(geometry());
    
    if (checkBoxAutoConnect->isChecked() && lineEditUserId->text() != "") {
        onPushBottonConnectClicked();
    }
}

void MainWindow::alwaysOnTopChanged(int state) {
    QRect rect = geometry();
    if (state == 2) {
        setWindowFlags(windowFlags() ^ Qt::WindowStaysOnTopHint);
    }
    else {
        setWindowFlags(windowFlags() & (~Qt::WindowStaysOnTopHint));
    }
    setGeometry(rect);
    show();
}

void MainWindow::onSystemTrayIconClicked(QSystemTrayIcon::ActivationReason reason) {
    if (reason == QSystemTrayIcon::Trigger) {
        if (isHidden()) show();
        else hide();
    }
}

void MainWindow::readSettings() {
    QSettings settings("Rui Diao", "CG^2");
   
    if (settings.contains("geometry")) {
        restoreGeometry(settings.value("geometry").toByteArray());
    }
    else {
        QDesktopWidget* desktop = QApplication::desktop(); // 窗口居中
        move((desktop->width() - this->width())/2, (desktop->height() - this->height())/2);
    }
    bool alwaysOnTop = settings.value("alwaysOnTop", false).toBool();
    if (alwaysOnTop) {
        setWindowFlags(windowFlags() | Qt::WindowStaysOnTopHint);
        checkBoxAlwaysOnTop->setChecked(true);
    }
    else {
        setWindowFlags(windowFlags() & (~Qt::WindowStaysOnTopHint));
        checkBoxAlwaysOnTop->setChecked(false);
    }
    bool autoReconnect = settings.value("autoReconnect", true).toBool();
    if (autoReconnect) {
        checkBoxAutoReconnect->setChecked(true);
    }
    else {
        checkBoxAutoReconnect->setChecked(false);
    }
    bool remember = settings.value("remember", true).toBool();
    if (remember) {
        checkBoxRemember->setChecked(true);
        lineEditUserId->setText(settings.value("userId", "").toString());
        lineEditPassword->setText(settings.value("password", "").toString());
        comboBoxDomain->setCurrentIndex(settings.value("domain", 1).toInt());
        comboBoxLoginType->setCurrentIndex(settings.value("loginType", 2).toInt());
    }
    else {
        checkBoxRemember->setChecked(false);
    }
    bool autoConnect = settings.value("autoConnect", false).toBool();
    if (autoConnect) {
        checkBoxAutoConnect->setChecked(true);
    }
    else {
        checkBoxAutoConnect->setChecked(false);
    }
    bool autoHide = settings.value("autoHide", false).toBool();
    if (autoHide) {
        checkBoxAutoHide->setChecked(true);
    }
    else {
        checkBoxAutoHide->setChecked(false);
    }
}

void MainWindow::saveSettings() {
    QSettings settings("Rui Diao", "CG^2");
    settings.setValue("geometry", saveGeometry());
    settings.setValue("alwaysOnTop", checkBoxAlwaysOnTop->isChecked());
    settings.setValue("autoReconnect", checkBoxAutoReconnect->isChecked());
    settings.setValue("autoConnect", checkBoxAutoConnect->isChecked());
    settings.setValue("autoHide", checkBoxAutoHide->isChecked());
}

void MainWindow::onPushBottonConnectClicked() {
    if (lineEditUserId->text() == "") {
        QMessageBox::warning(this, tr("错误"), tr("请填写用户名"));
        return;
    }
    
    if (lineEditPassword->text() == "") {
        QMessageBox::warning(this, tr("错误"), tr("请填写密码"));
        return;
    }
    
    QSettings settings("Rui Diao", "CG^2");
    settings.setValue("remember", checkBoxRemember->isChecked());
    if (checkBoxRemember->isChecked()) {
        settings.setValue("userId", lineEditUserId->text());
        settings.setValue("password", lineEditPassword->text());
        settings.setValue("domain", comboBoxDomain->currentIndex());
        settings.setValue("loginType", comboBoxLoginType->currentIndex());
    }    
        
    userId = lineEditUserId->text();
    password = lineEditPassword->text();
    domain = comboBoxDomain->currentIndex();
    loginType = comboBoxLoginType->currentIndex();
    loginGateway();
}

void MainWindow::loginGateway() {
    QString data(QString("domainid=") + QUrl::toPercentEncoding(QString("%1").arg(domain + 1)) + QString("&loginuser=") + QUrl::toPercentEncoding(userId) + QString("&password=") + QUrl::toPercentEncoding(password) + QString("&logintype="));

    data += "%D7%D4%B7%FE%CE%F1";//自服务
    QHttpRequestHeader header("POST", "/php/user_login.php") ;
    header.setValue("Host", host);
    header.setValue("USER_AGENT", userAgent);
    header.setContentType("application/x-www-form-urlencoded");
    httpLogin->setHost(host, QHttp::ConnectionModeHttps);
    httpLogin->request(header, data.toUtf8());
}

void MainWindow::getCookie(const QHttpResponseHeader &resp) {
    cookie = resp.allValues("set-cookie");
}

void MainWindow::checkLogin(bool error) {
    qDebug() << "check login" << endl;
    if (error) {
        qDebug() << "http error\n";
        QMessageBox::warning(this, tr("网络错误"), tr("请检查网络连接"));
        return;
    }
    else {
        QString page = httpLogin->readAll();
        QTextCodec *utf = QTextCodec::codecForName("GB2312");
        qDebug() << utf->toUnicode(page.toLatin1().data());
        if (utf->toUnicode(page.toLatin1().data()).contains(tr("欢迎您使用计费系统"))) { //此处需要检验是否登录成功
            connectNetwork();
        }
        else if (utf->toUnicode(page.toLatin1().data()).contains(tr("用户名或密码错误"))) { //用户名或密码错误
            QMessageBox::warning(this, tr("登录错误"), tr("用户名或密码错误"));
        }
        else if (utf->toUnicode(page.toLatin1().data()).contains(tr("错误的用户名或密码"))) { //用户名或密码错误
            QMessageBox::warning(this, tr("登录错误"), tr("错误的用户名或密码"));
        }
        else {
            QMessageBox::warning(this, tr("登录错误"), tr("登录错误"));
        }
    }
}

void MainWindow::connectNetwork() {
    httpConnect->setHost(host, QHttp::ConnectionModeHttps);
    QHttpRequestHeader header("GET", QString("/php/login_net.php?mode=%1").arg(loginType));
    header.setValue("Host", host);
    header.setValue("USER_AGENT", userAgent);
    foreach (QString str, cookie) {
        header.setValue("cookie", str);
    }
    header.setContentType("application/x-www-form-urlencoded");
    httpConnect->request(header);
}

void MainWindow::checkConnect(bool error) {
    if (error) {
        qDebug() << "http error\n";
        QMessageBox::warning(this, tr("网络错误"), tr("请检查网络连接"));
        return;
    }
    else {
        QString page = httpConnect->readAll();
        QTextCodec *utf = QTextCodec::codecForName("GB2312");
        qDebug() << utf->toUnicode(page.toLatin1().data());
        if (utf->toUnicode(page.toLatin1().data()).contains(tr("用户已经在此IP连线了"))) {
            qDebug() << tr("用户已经在此IP连线了") << endl;
            if (QMessageBox::No == QMessageBox::question(this, tr("错误"), tr("您已经在此IP连线了，需要重新连线吗？"), QMessageBox::Yes | QMessageBox::No)) {
                updateMessage();//更新一次
                updateRemainFee();
                timerUpdate->start(60 * 1000);//一分钟更新一次
                tabWidget->setCurrentIndex(1);
                if (checkBoxAutoHide->isChecked()) {
                    hide();
                }
            }
            else {
                disconnectNetwork();
            }
        }
        else if (utf->toUnicode(page.toLatin1().data()).contains(tr("您已经成功连线"))) {
            qDebug() << tr("您已经成功连线") << endl;
            updateMessage();//更新一次
            updateRemainFee();
            timerUpdate->start(60 * 1000);//一分钟更新一次
            tabWidget->setCurrentIndex(1);
            if (checkBoxAutoHide->isChecked()) {
                hide();
            }
        }
        else if (utf->toUnicode(page.toLatin1().data()).contains(tr("您的帐号已达到最大连线数"))) {
            QRegExp rxIp("(\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3})");
            if (-1 == rxIp.indexIn(page)) {
                QMessageBox::warning(this, tr("连线失败"), tr("您的帐号已达到最大连线数"));
            }
            else {
                QString ip = rxIp.cap(1);
                QRegExp rxDate("(\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2})");
                rxDate.indexIn(page);
                QString date = rxDate.cap(1);
                if (QMessageBox::Yes == QMessageBox::question(this, tr("连线失败"), tr("您的帐号已达到最大连线数。用户") + ip + tr("于") + date + tr("连线网络，需要把Ta踢下线并重新连线吗？"), QMessageBox::Yes | QMessageBox::No)) {
                    kickOff(ip);
                }
            }
        }
        else if (utf->toUnicode(page.toLatin1().data()).contains(tr("已经存在其他用户在此IP连线,而且无法强制退出"))) {
            if (QMessageBox::Yes == QMessageBox::question(this, tr("连线失败"), tr("已经存在其他用户在此IP连线，需要退出该用户，并用现在的用户设定重新连线吗？"), QMessageBox::Yes | QMessageBox::No)) {
                disconnectNetwork();
            }
        }
        else {
            int pos = 0;
            QRegExp rx("<div align=\"center\"><font color=\"#FFFFFF\">([^<]*)</font></div>");
            pos = rx.indexIn(page, pos);
            qDebug() << "pos = " << pos << endl;
            if (pos == -1) {
                QMessageBox::critical(this, tr("连线失败"), tr("无法获取错误原因。"));
                return;
            }
            QString title = rx.cap(1);
            pos += rx.matchedLength();
            pos = rx.indexIn(page, pos);
            if (pos == -1) {
                QMessageBox::critical(this, tr("连线失败"), tr("无法获取错误原因。"));
                return;
            }
            QString content = rx.cap(1);
            QMessageBox::warning(this, utf->toUnicode(title.toLatin1().data()), utf->toUnicode(content.toLatin1().data()));
        }
    }
}

void MainWindow::updateMessage() {
    httpMessage->setHost(host, QHttp::ConnectionModeHttps);
    QHttpRequestHeader header("GET", QString("/php/onlinestatus.php"));
    header.setValue("Host", host);
    header.setValue("USER_AGENT", userAgent);
    foreach (QString str, cookie) {
        header.setValue("cookie", str);
    }
    header.setContentType("application/x-www-form-urlencoded");
    httpMessage->request(header);
}

void MainWindow::updateRemainFee() {
    httpRemainFee->setHost(host, QHttp::ConnectionModeHttps);
    QHttpRequestHeader header("GET", QString("/php/remain_fee.php"));
    header.setValue("Host", host);
    header.setValue("USER_AGENT", userAgent);
    foreach (QString str, cookie) {
        header.setValue("cookie", str);
    }
    header.setContentType("application/x-www-form-urlencoded");
    httpRemainFee->request(header);
}

void MainWindow::checkMessage(bool error) {
    if (error) {
        qDebug() << "http error\n";
    }
    else {
        qDebug() << "check message\n";
        QString page = httpMessage->readAll();
        QTextCodec *utf = QTextCodec::codecForName("GB2312");
        
        if (utf->toUnicode(page.toLatin1().data()).contains(tr("您没有从本机登录网络"))) { //断线自动重新连接
            if (checkBoxAutoReconnect->isChecked()) {
                connectNetwork();
            }
            return;
        }
        
        if (utf->toUnicode(page.toLatin1().data()).contains(tr("登录错误"))) { //断线自动重新连接
            if (checkBoxAutoReconnect->isChecked()) {
                loginGateway();
            }
            return;
        }
        
        QRegExp rx("((\\d|,)+\\.\\d{2})&nbsp;Mb");
        int i, pos = 0;
        QStringList megaByte;
        for (i = 0; i < 6; i++) {
            pos = rx.indexIn(page, pos);
            if (pos == -1) {
                qDebug() << "no match digits\n";
                return;
            }
            else {
                megaByte << rx.cap(1) + " M ";
                qDebug() << rx.cap(1) << endl;
                pos += rx.matchedLength();
            }
        }
        for (i = 0; i < 6; i++) {
            findChild<QLabel *>(labelNameList[i])->setText(megaByte[i]);
        }

        if (utf->toUnicode(page.toLatin1().data()).contains(tr("<div align=\"center\">城域</div>"))) {
            labelConnectType->setText(tr("连线方式：城域"));
            //setWindowTitle(tr("连线城域-中国科学院研究生院网关客户端"));
            toolTip[0] = tr("连线方式：城域\n本月流量：\n");
        }
        if (utf->toUnicode(page.toLatin1().data()).contains(tr("<div align=\"center\">国内</div>"))) {
            labelConnectType->setText(tr("连线方式：国内"));
            //setWindowTitle(tr("连线国内-中国科学院研究生院网关客户端"));
            toolTip[0] = tr("连线方式：国内\n本月流量：\n");
        }
        if (utf->toUnicode(page.toLatin1().data()).contains(tr("<div align=\"center\">国际</div>"))) {
            labelConnectType->setText(tr("连线方式：国际"));
            //setWindowTitle(tr("连线国际-中国科学院研究生院网关客户端"));
            toolTip[0] = tr("连线方式：国际\n本月流量：\n");
        }
        toolTip[0] += tr("城域：") + megaByte[0] + tr("↑") + " " + megaByte[1] + tr("↓\n")
          + tr("国内：") + megaByte[2] + tr("↑") + " " + megaByte[3] + tr("↓\n")
          + tr("国际：") + megaByte[4] + tr("↑") + " " + megaByte[5] + tr("↓\n");
        toolTip[2] = tr("最后更新于") + QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss");
        trayIcon->setToolTip(toolTip[0] + toolTip[1] + toolTip[2]);
        labelUpdateTime->setText(tr("最后更新于") + QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss"));
    }
}

void MainWindow::checkRemainFee(bool error) {
    if (error) {
        qDebug() << "http error\n";
    }
    else {
        qDebug() << "check remain fee\n";
        QString page = httpRemainFee->readAll();
        QRegExp rx("((\\d|,)+\\.\\d{2})");
        int pos;
        pos = rx.indexIn(page);
        if (pos == -1) {
            qDebug() << "no match digits\n";
        }
        else {
            labelRemainFee->setText(tr("当前余额：%1元").arg(rx.cap(1)));
            toolTip[1] = tr("当前余额：%1元\n").arg(rx.cap(1));
            trayIcon->setToolTip(toolTip[0] + toolTip[1] + toolTip[2]);
            qDebug() << rx.cap(1) << endl;
        }
    }
}


void MainWindow::disconnectNetwork() {
    qDebug() << "disconnectNetwork()" << endl;
    timerUpdate->stop();
    httpDisconnect->setHost(host, QHttp::ConnectionModeHttps);
    QHttpRequestHeader header("GET", QString("/php/logout_net.php"));
    header.setValue("Host", host);
    header.setValue("USER_AGENT", userAgent);
    foreach (QString str, cookie) {
        header.setValue("cookie", str);
    }
    header.setContentType("application/x-www-form-urlencoded");
    httpDisconnect->request(header);
}

void MainWindow::closeEvent(QCloseEvent *event) {
    quit = true;
    saveSettings();
    if (timerUpdate->isActive()) {
        disconnectNetwork();
        if (QMessageBox::Close == QMessageBox::information(this, tr("退出"), tr("正在离线，离线后会自动退出程序。点击下面按钮强制退出程序。"), QMessageBox::Close)) {
            QCoreApplication::quit();
        }
    }
    else {
        QCoreApplication::quit();
    }
}

void MainWindow::onDisconnected(bool error) {
    if (error) {
        qDebug() << "http error\n";
        QMessageBox::warning(this, tr("网络错误"), tr("请检查网络连接"));
    }
    if (quit) {
        QCoreApplication::quit();
    }
    else {
        connectNetwork();
    }
}

void MainWindow::kickOff(QString ip) {
    QString data(QString("ip=") + QUrl::toPercentEncoding(ip) + QString("&password=") + QUrl::toPercentEncoding(password));
    httpKickOff->setHost(host, QHttp::ConnectionModeHttps);
    QHttpRequestHeader header("POST", QString("/php/kickself.php"));
    header.setValue("Host", host);
    header.setValue("USER_AGENT", userAgent);
    foreach (QString str, cookie) {
        header.setValue("cookie", str);
    }
    header.setContentType("application/x-www-form-urlencoded");
    httpKickOff->request(header, data.toUtf8());
}
